package com.lxd.milktea.controller;


import com.lxd.milktea.VO.MaterialVO;
import com.lxd.milktea.VO.ProductInfoVO;
import com.lxd.milktea.VO.ProductVO;
import com.lxd.milktea.VO.ResultVO;
import com.lxd.milktea.dataobject.*;
import com.lxd.milktea.enums.StockEnum;
import com.lxd.milktea.form.MaterialRe;
import com.lxd.milktea.form.ProductForm;
import com.lxd.milktea.form.ProductReForm;
import com.lxd.milktea.service.CategoryService;
import com.lxd.milktea.service.MaterialService;
import com.lxd.milktea.service.ProductService;
import com.lxd.milktea.service.StockService;
import com.lxd.milktea.util.KeyUtil;
import com.lxd.milktea.util.ResultVOUtil;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author Ha
 * @DATE 2019/6/27 21:27
 **/
@Controller
@Slf4j
@RequestMapping("/product")
@Api(value = "产品控制器")
public class ProductController {
    private final ProductService productService;
    private final CategoryService categoryService;
    private final MaterialService materialService;
    private final StockService stockService;

    public ProductController(ProductService productService, CategoryService categoryService, MaterialService materialService, StockService stockService) {
        this.productService = productService;
        this.categoryService = categoryService;
        this.materialService = materialService;
        this.stockService = stockService;
    }

    /**
     * 1. 查询所有在架的商品
     * 2. 获取类目type列表
     * 3. 查询类目
     * 4. 构造数据
     */
    @GetMapping("/listUp")
    @ApiOperation(value = "获取上架产品列表")
    @ResponseBody
    public ResultVO<ProductVO> list() {
        //1. 查询所有在架的商品
        List<ProductInfo> productInfoList = productService.findUpAll();

        //2. 获取类目type列表
        List<Integer> categoryTypeList = productInfoList.stream()
                .map(ProductInfo::getCategoryType)
                .collect(Collectors.toList());

        //3. 从数据库查询类目
        List<Category> categoryList = categoryService.findByCategoryTypeIn(categoryTypeList);

        //4. 构造数据
        List<ProductVO> productVOList = new ArrayList<>();
        for (Category productCategory: categoryList) {
            ProductVO productVO = new ProductVO();
            productVO.setCategoryName(productCategory.getCategoryName());
            productVO.setCategoryType(productCategory.getCategoryType());

            List<ProductInfoVO> productInfoVOList = new ArrayList<>();
            for (ProductInfo productInfo: productInfoList) {
                if (productInfo.getCategoryType()==productCategory.getCategoryType()) {
                    ProductInfoVO productInfoVO = new ProductInfoVO();
                    BeanUtils.copyProperties(productInfo, productInfoVO);
                    productInfoVOList.add(productInfoVO);
                }
            }
            productVO.setProductInfoVOList(productInfoVOList);
            productVOList.add(productVO);
        }

        return ResultVOUtil.success(productVOList);
    }

    /**
     * 列表
     * @param page
     * @param size
     * @return
     */
    @GetMapping("/list")
    @ApiOperation(value = "获取所有产品的分页列表")
    @ResponseBody
    public ResultVO<HashMap> list(@RequestParam(value = "page",defaultValue = "1")
                             @ApiParam(name="page",value="页数",required=false,defaultValue = "1")
                             Integer page,
                                  @RequestParam(value = "size",defaultValue = "10")
                             @ApiParam(name="size",value="页大小",required=false,defaultValue = "10")
                             Integer size){
        PageRequest pageRequest = PageRequest.of(page-1,size);
        Page<ProductInfo> ProductInfoPage = productService.findAll(pageRequest);
        Map<String,Object> map = new HashMap<>();
        map.put("ProductInfoPage",ProductInfoPage);
        map.put("currentPage",page);
        map.put("pageSize",size);
        return ResultVOUtil.success(map);
    }

    @PostMapping("on_sale")
    @ApiOperation(value = "上架某个产品")
    @ResponseBody
    public ResultVO onSale(@RequestParam(value = "productId")
                           @ApiParam(name="productId",value="产品ID",required=true)
                           String productInfoId){
        try {
            productService.onSale(productInfoId);
        }catch (Exception e){
            return ResultVOUtil.fail(500,e.getMessage());
        }
        return ResultVOUtil.success();
    }

    @PostMapping("off_sale")
    @ApiOperation(value = "下架某个产品")
    @ResponseBody
    public ResultVO offSale(@RequestParam(value = "productId")
                            @ApiParam(name="productId",value="产品ID",required=true)
                            String productInfoId,Map<String,Object> map){
        try {
            productService.OffSale(productInfoId);
        }catch (Exception e){
            return ResultVOUtil.fail(500,e.getMessage());
        }
        return ResultVOUtil.success();
    }

    @PostMapping("save")
    @ApiOperation(value = "新增或保存产品")
    @ResponseBody
    @ApiResponses({
            @ApiResponse(code = 400 ,message = "原料不足"),
            @ApiResponse(code = 500 ,message = "服务器后台问题"),
            @ApiResponse(code = 0 ,message = "成功")
    })
    public ResultVO save(@Valid @ModelAttribute ProductForm productForm, BindingResult bindingResult){
        if(bindingResult.hasErrors()){
            return ResultVOUtil.fail(500,bindingResult.getFieldError().getDefaultMessage());
        }
        ProductInfo productInfo = new ProductInfo();
        //判断一下id是不是为空，为空说明是新增
        try{
            if(StringUtils.isEmpty(productForm.getProductId())){
                //新增操作,生成新的商品ID
                productForm.setProductId(KeyUtil.genUniqueKey());
            }else {
                //更新操作，找到原有的商品
                productInfo = productService.findOne(productForm.getProductId());
                if(!productForm.getProductStock().equals(productInfo.getProductStock())){
                    ResultVO sb = updateStock(productForm, productInfo);
                    if (sb != null) {
                        return sb;
                    }
                }
            }
            BeanUtils.copyProperties(productForm,productInfo);
            productService.save(productInfo);
        }catch (Exception e){
            return ResultVOUtil.fail(500,e.getMessage());
        }
        return ResultVOUtil.success();
    }

    /**
     * 更新库存方法
     * @param productForm
     * @param productInfo
     * @return
     */
    private ResultVO updateStock(@Valid ProductForm productForm, ProductInfo productInfo) {
        int i = productForm.getProductStock()-productInfo.getProductStock();
        List<MaterialVO> materialVOList = productService.getProductForm(productInfo.getProductId());
        if(materialVOList==null||materialVOList.isEmpty()){
            //没有组成，直接跳出
            return null;
        }
        List<String> ids = materialVOList.stream().map(MaterialVO::getId).collect(Collectors.toList());
        Map<String, Integer> collect = materialVOList.stream().collect(Collectors.toMap(MaterialVO::getId, materialVO -> materialVO.getNeedNum()*i));
        List<Material> list = materialService.findList(ids);
        //库存不足的原料
        List<Material> stockLess = list.stream().filter(material -> material.getStock() < collect.get(material.getId())).collect(Collectors.toList());
        if(!stockLess.isEmpty()){
            StringBuilder sb = new StringBuilder("原料 ");
            for(Material m:stockLess){
                sb.append(m.getMaterialName()+" ");
            }
            sb.append("不足");
            return ResultVOUtil.fail(400,sb.toString());
        }
        if(i>0){
            //增加库存，减少原料数量 在stock中记录操作
            list.stream().forEach(material -> {
                StockInfo stockInfo = new StockInfo();
                stockInfo.setMaterialId(material.getId());
                stockInfo.setType(StockEnum.OUT.getType().byteValue());
                stockInfo.setNum(-i);
                stockInfo.setNowStock(material.getStock()-collect.get(material.getId()));
                stockInfo.setSettleDate(new Timestamp(System.currentTimeMillis()));
                stockService.addStock(stockInfo);
            });
        }else{
            list.stream().forEach(material -> {
                StockInfo stockInfo = new StockInfo();
                stockInfo.setMaterialId(material.getId());
                stockInfo.setType(StockEnum.BALANCE.getType().byteValue());
                stockInfo.setNum(+i);
                stockInfo.setNowStock(material.getStock()-collect.get(material.getId()));
                stockInfo.setSettleDate(new Timestamp(System.currentTimeMillis()));
                stockService.addStock(stockInfo);
            });
        }
        list.stream().forEach(material -> material.setStock(material.getStock()-collect.get(material.getId())));
        list.stream().forEach(material -> materialService.save(material));
        return null;
    }

    /**
     * 查看商品信息
     */
    @GetMapping("index")
    @ResponseBody
    @ApiOperation(value = "查看商品信息")
    public ResultVO index(@RequestParam(value = "productId",required = false)String productID,Map<String,Object> map){
        if(!StringUtils.isEmpty(productID)){
            ProductInfo productInfo = productService.findOne(productID);
            map.put("productInfo",productInfo);
        }
        //查询所有的类目
        List<Category> all = categoryService.findAll();
        map.put("categoryList",all);
        //查询产品原料子关系
        List<ProductRe> productRe = productService.findProductRe(productID);
        //构建原料ID集合和原料ID-所需量map
        List<String> MaterialIDs = productRe.stream().map(ProductRe::getMaterialId).collect(Collectors.toList());
        Map<String, Integer> needNum = productRe.stream().collect(Collectors.toMap(ProductRe::getMaterialId, ProductRe::getNeedNum));
        //查询产品的原料信息
        List<Material> list = materialService.findList(MaterialIDs);
        //构建VO
        List<MaterialVO> productReList = list.stream().map(material -> {
            MaterialVO vo = new MaterialVO();
            vo.setNeedNum(needNum.get(material.getId()));
            vo.setStock(material.getStock());
            vo.setPic(material.getPic());
            vo.setMaterialName(material.getMaterialName());
            vo.setId(material.getId());
            return vo;
        }).collect(Collectors.toList());
        //放置VO到map结果集中
        map.put("productReList",productReList);
        //查询原料列表
        List<Material> materialList = materialService.findAll();
        //放置原料列表到结果集中
        map.put("materialList",materialList);
        return ResultVOUtil.success(map);
    }

    /**
     * 更新产品配方
     * todo test
     */
    @ResponseBody
    @PostMapping("saveRe")
    @ApiOperation(value = "更新产品配方,使用json的格式提交产品的原料进行更新")
    public ResultVO saveRe(@RequestBody ProductReForm form){
        //查询原料参数是否合法
        List<String> ids = form.getList().stream().map(MaterialRe::getMaterialId).collect(Collectors.toList());
        List<Material> list = materialService.findList(ids);
        if(ids.size() != list.size()){
            //参数不合法
            return ResultVOUtil.fail(400,"原料不存在");
        }
        //删除 添加
        productService.deleteProductRe(form.getProductId());
        productService.saveProductRe(form.getProductId(),form.getList());
        return ResultVOUtil.success();
    }



}
